import {
  cloneVNode,
  defineComponent,
  h,
  onMounted,
  ref,
  Text,
  watch
} from 'vue';
import TreeSelect from './components/select.vue';
import SelectPane from './components/selectPane.vue';
import SvgIcon from '@/components/icon/index.vue';
import { getDeptData, type TreeNodeData } from '@/api/common';
import { flatTreeData, fmtToTData } from './utils';
import { type SSModelValue, type TData, SelecterProps } from './props';
import { getFirstSlotVNode } from '@/utils/index';
import useFloat from '@/hooks/useFloat';
export type { TData } from './props';

export default defineComponent({
  name: 'DeptSelect',
  props: SelecterProps,
  emits: ['update:modelValue', 'change'],
  setup(props, ctx) {
    const loading = ref(false);

    const options = ref<TData[]>([]);

    const selectedValue = ref<SSModelValue>();

    const updateSelectValue = () => {
      if (props.multiple) {
        const targets: TData[] = [];
        // 收窄类型
        (props.modelValue as string[])?.forEach((id: string) => {
          const target = flatTreeData(options.value).find(
            (u: TData) => u.id == id
          );
          if (target) targets.push(target);
        });
        selectedValue.value = targets.length > 0 ? targets : undefined;
      } else {
        selectedValue.value = flatTreeData(options.value).find(
          (item: TData) => item.id == props.modelValue
        );
      }
    };

    const fmtResponseData = (response: TreeNodeData[]) => {
      const result: TData[] = [];
      for (const rsp of response) {
        const res = fmtToTData(rsp, props.disabledMethod, props.filterMethod);
        if (res !== undefined) result.push(res);
      }
      options.value = result;
    };

    const refresh = async () => {
      loading.value = true;
      try {
        const response = await getDeptData();
        fmtResponseData(response);
      } catch (error) {
        return await Promise.reject(error);
      } finally {
        loading.value = false;
      }
    };

    watch(props, updateSelectValue);

    onMounted(refresh);

    const { open, close } = useFloat('dialog', SelectPane);
    const openDailog = () => {
      open({
        title: props.placeholder,
        closeOnClickModal: true,
        props: {
          modelValue: selectedValue.value,
          multiple: props.multiple,
          loading: loading.value,
          type: 1,
          options: options.value,
          onRefresh: () => refresh(),
          onChange: (val?: TData[] | TData) => {
            selectedValue.value = val;
            ctx.emit(
              'update:modelValue',
              Array.isArray(val) ? val.map((item) => item.id) : val?.id
            );
            ctx.emit('change', val);
            close();
          },
          onClose: close
        }
      });
    };

    return () => {
      if (props.mode === 'button') {
        let triggerNode = getFirstSlotVNode(ctx.slots);
        if (triggerNode) {
          triggerNode =
            triggerNode.type === Text
              ? h('span', { style: { cursor: 'pointer' } }, [triggerNode])
              : triggerNode;
          triggerNode = cloneVNode(triggerNode, {
            onClick: (e: Event) => {
              e.stopPropagation();
              if (props.disabled) return;
              openDailog();
            }
          });
        }

        return h(triggerNode!);
      }
      return h(
        TreeSelect,
        {
          ...ctx.attrs,
          modelValue: selectedValue.value,
          placeholder: props.placeholder,
          disabled: props.disabled,
          multiple: props.multiple,
          size: props.size,
          options: options.value,
          type: 1,
          onOpenDailog: () => openDailog(),
          'onUpdate:modelValue': (val?: TData[] | TData) => {
            selectedValue.value = val;
            ctx.emit(
              'update:modelValue',
              Array.isArray(val) ? val.map((item) => item.id) : val?.id
            );
          },
          onChange: (val: any) => ctx.emit('change', val)
        },
        {
          icon: () =>
            h(SvgIcon, { name: 'department', style: { color: '#ddd' } })
        }
      );
    };
  }
});
